package unit4

import (
	"fmt"
	"log"
)

type MyCircularQueue struct {
	items    []int
	size     int
	frontIdx int
	rearIdx  int
}

func (m *MyCircularQueue) Show() {
	for i := 0; i < m.Length(); i++ {
		fmt.Println("Show ", m.items[(m.frontIdx+i)%m.size])
	}
}

func (m *MyCircularQueue) Length() int {
	if m.IsEmpty() {
		return 0
	}
	if m.frontIdx < m.rearIdx {
		return m.rearIdx - m.frontIdx
	} else if m.frontIdx > m.rearIdx {
		return m.rearIdx + m.size - m.frontIdx + 1
	} else {
		return 1
	}
}

func (m *MyCircularQueue) Front() int {
	if m.IsEmpty() {
		return -1
	}
	return m.items[m.frontIdx]
}

func (m *MyCircularQueue) Rear() int {
	if m.IsEmpty() {
		return -1
	}
	return m.items[m.rearIdx]
}

func (m *MyCircularQueue) EnQueue(n int) bool {
	if m.IsFull() {
		return false
	}

	// 处理前后指针
	if m.IsEmpty() {
		m.frontIdx++
	}
	m.rearIdx = (m.rearIdx + 1) % m.size
	m.items[m.rearIdx] = n
	return true
}

func (m *MyCircularQueue) DeQueue() bool {
	if m.IsEmpty() {
		return false
	}
	if m.frontIdx == m.rearIdx {
		m.frontIdx, m.rearIdx = -1, -1
		//m.items = m.items[0:0]
		return true
	}
	m.frontIdx = (m.frontIdx + 1) % m.size

	return true
}

func (m *MyCircularQueue) IsEmpty() bool {
	if m.frontIdx == -1 && m.rearIdx == -1 {
		return true
	}
	return false
}

func (m *MyCircularQueue) IsFull() bool {
	if m.frontIdx < m.rearIdx {
		if m.rearIdx-m.frontIdx == m.size-1 {
			return true
		}
	} else if m.frontIdx > m.rearIdx {
		if m.frontIdx-m.rearIdx == 1 {
			return true
		}
	} else {
		return false
	}
	return false
}

/** Initialize your data structure here. Set the size of the queue to be k. */
func Constructor(k int) MyCircularQueue {
	return MyCircularQueue{
		items:    make([]int, k),
		size:     k,
		frontIdx: -1,
		rearIdx:  -1,
	}
}

func t1() bool {
	circularQueue := Constructor(3)

	log.Println(circularQueue.EnQueue(6))
	log.Println(circularQueue.Rear())
	log.Println(circularQueue.Rear())
	log.Println(circularQueue.DeQueue())
	log.Println(circularQueue.EnQueue(5))
	log.Println(circularQueue.Rear())
	log.Println(circularQueue.DeQueue())
	log.Println(circularQueue.Front())
	log.Println(circularQueue.DeQueue())
	log.Println(circularQueue.DeQueue())
	log.Println(circularQueue.DeQueue())

	//log.Println(circularQueue.EnQueue(1)) // 返回 true
	//log.Println(circularQueue.EnQueue(2)) // 返回 true
	//log.Println(circularQueue.EnQueue(3)) // 返回 true
	//log.Println(circularQueue.EnQueue(4)) // 返回 false，队列已满
	//log.Println(circularQueue.Rear())     // 返回 3
	//log.Println(circularQueue.IsFull())   // 返回 true
	//log.Println(circularQueue.DeQueue())  // 返回 true
	//log.Println(circularQueue.EnQueue(4)) // 返回 true
	//log.Println(circularQueue.Rear())     // 返回 true

	//log.Println(circularQueue.EnQueue(4))           // 返回 true
	//log.Println("Length: ", circularQueue.Length()) // 返回 true
	//circularQueue.Show() // 返回 true
	//log.Println(circularQueue.EnQueue(4)) // 返回 true
	//log.Println(circularQueue.Rear())     // 返回 4

	fmt.Printf(
		"items %#v \nfront %#v \nrear %#v\n",
		circularQueue.items,
		circularQueue.frontIdx,
		circularQueue.rearIdx,
	)

	return true
}
